package com.bangdream.michelia.tool.retrofithttp;


import android.app.Dialog;
import android.util.Log;

import com.bangdream.michelia.entity.BaseEntity;

import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
import io.reactivex.subjects.Subject;


public abstract class TokenManager<T> {
    private static final String TAG = "token_log";
    private volatile Subject<T> subject;

    private static int mRetryCount=0;
    private volatile AtomicBoolean isSend;

    public Dialog pd;

    public Dialog getPd() {
        return pd;
    }

    public void setPd(Dialog pd) {
        this.pd = pd;
    }

    public TokenManager() {
        subject = PublishSubject.create();
        isSend = new AtomicBoolean();
    }

    public static Observable work(Create create) {
        return Observable.defer((Callable<ObservableSource<? extends BaseEntity>>) () -> create.create())
                .map(TokenManagerDef.checkedToken());
    }


    public interface Create{
        Observable<? extends BaseEntity> create();
    }

    public Subject<T> getSubject() {
        //没有发送
        if (isSend.compareAndSet(false, true)) {
            createTokenObservableAndSend();
        } else {
        }
        return subject;
    }

    protected void sendSuccess(T t) {
        if (isSend.compareAndSet(true, false)) {
                subject.onNext(t);
        }
    }


    /**
     * 生成token
     */
    abstract void createTokenObservableAndSend();

    /**
     * 是否拦截
     */
    abstract boolean intercept(Throwable throwable);


    abstract boolean isOK(T t);

    public ObservableTransformer<T, T> getTransformer() {
        return upstream -> upstream.retryWhen((Function<Observable<Throwable>, ObservableSource<T>>) throwableObservable -> {
            return throwableObservable.flatMap((Function<Throwable, ObservableSource<T>>) throwable -> {
                if (intercept(throwable)) {
                    return getSubject().flatMap(new Function<T, ObservableSource<T>>() {
                        @Override
                        public ObservableSource<T> apply(T t) throws Exception {

                            if (mRetryCount > 1) {
                                return Observable.error(new Exception("获取token失败"));
                            }
                            if (!isOK(t))
                                Observable.error(new Exception("获取token失败"));
                            mRetryCount++;
                            return Observable.just(t);
                        }
                    });
                } else {
                    return Observable.error(throwable);
                }

            });
        });
    }

}
